iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0

以下內容皆參考 Backtrader 官網

之前有介紹過,如果我們下單除了股價以外,還有一個很重要的因素就是要買幾股,有些時候,我們的策略可能會需要不同的買入數量,Backtrader 也有一個物件 sizer 可以提供相關的彈性,如果預設的沒有合適的,也可以自訂義一個,以下先介紹內建的一些 sizer

FixedSize

顧名思義就是固定的數量
參數:

  • stake { default 1 }: 固定數量的股數
  • tranches { default 1 }: 只執行 stake 的幾分之一
    最後的數量 = stake / tranches
cerebro.addsizer(bt.sizers.SizerFix, stake = 1000)

FixedReverser

一樣是固定數量,只是在賣的時候,會賣出 2 倍的庫存,也就是把正的庫存賣成負的庫存
參數:

  • stake { default 1 } 固定的股數
cerebro.addsizer(bt.sizers.FixedRevert, stake = 1000)

PercentSizer

使用一定比例的帳戶餘額去買進
參數:

  • percents { default 20 }: 20%
cerebro.addsizer(bt.sizers.PercentSizer, percents = 80)

AllInSizer

基本上和 PercentSizer 一樣,只是預設是 100% 的帳戶餘額去買進股票,另一個差別就是 All in 聽起來比較霸氣。
這裡有一個要注意的是,AllIn 是以當天的收盤價去算要買的股數,可是在執行買入的時候,是隔天的開盤價,所以隔天是漲的話,就會造成餘額不足,買入失敗喔

cerebro.addsizer(bt.sizers.AllInSizer)

其它

PercentSizerInt, AllInSizerInt,這兩個看說明是說在回傳數量的時候會轉成整數,不過我真正去執行的結果,兩個都是一樣的,所以暫時看不出差別

自訂義 sizer

要自訂義 sizer 也很簡單

  • 訂義一個 sizer 的 class 繼承 backtrader.Sizer
    繼承後可以使用 self.strategy 和 self.broker 來取得相關資料

    • 取得庫存 self.strategy.getposition(data)
    • 取得目前淨值 self.broker.getvalue() (或是 self.stratgy.broker.getvalue())
  • 覆寫 _getsizing(self, comminfo, cash, data, isbuy)

    • comminfo: 手續費相關資訊
    • cash:目前帳戶餘額
    • data: 目前的操作(買入/賣出)資料
    • isbuy: 是否為買入(True)

例如:改寫 percent 變成可以買的最大的張數 ( 1000 股 )

import backtrader as bt
import math
class PercentBoardSizer(bt.Sizer):
    params = (
        ('percents', 20),
    )

    def _getsizing(self, comminfo, cash, data, isbuy):
        position = self.broker.getposition(data)
        if not position:
            size = cash / data.close[0] * (self.p.percents / 100)
            
            if size < 1000:
                # 小於 1000 股,就不買
                size = 0
            else:
                size = math.floor(size / 1000) * 1000
        else:
            size = position.size

        size = int(size)
        
        return size

class AllInBoardSizer(PercentBoardSizer):
    params = (
        ('percents', 100),
    )

使用方法

  • 在 strategy 中:

    • def setsizer(self, sizer): 可以取得已經初始化的 sizer
    • def getsizer(self): 回傳目前使用的 sizer
    • sizer 屬性可以直接進行 get/set (前幾天的範例就是使用這個)
  • 使用 cerebro:
    目前看來,如果 strategy 和 cerebro 都有設定的話,會以 cerebro 為主,cerebro 有兩個方法可以設定

    • addsizer(sizerClass, *args, **kwargs): 指定所有的 strategy 使用的 sizer
    • addsizer_byidx(idx, sizerClass, *args, **kwargs): 根據不同的 strategy inx 來使用不同的 sizer
      ex:
    cerebro = bt.Cerebro()
    # 預設的 sizer
    cerebro.addsizer(bt.sizers.SizerFix, stake = 1000)
    
    # 這樣就可以針對不同的 strategy 來設定不同的 sizer
    idx = cerebro.addstrategy(TestStrategy)
    cerebro.addsizer_byidx(idx, bt.sizers.SizerFix, stake = 5)
    

上一篇
Backtrader - 自訂 datafeeds
下一篇
策略實作 - 葛蘭碧八法
系列文
永豐金融APIs - 從零開始到放棄!?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言